package cn.qihua.security;

import java.io.IOException;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

public class CaptchaFormAuthenticationFilter extends FormAuthenticationFilter {

	/**
	 * 验证码参数名
	 */
	public static final String DEFAULT_CAPTCHA_PARAM = "captcha";
	protected String captchaParam = DEFAULT_CAPTCHA_PARAM;

	public String getCaptchaParam() {
		return captchaParam;
	}

	public void setCaptchaParam(String captchaParam) {
		this.captchaParam = captchaParam;
	}

	protected String getCaptcha(ServletRequest request) {
		return WebUtils.getCleanParam(request, getCaptchaParam());
	}

	/*
	 * 主要是针对登入成功的处理方法。对于请求头是AJAX的之间返回JSON字符串。
	 */
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token,
			Subject subject, ServletRequest request, ServletResponse response)
			throws Exception {
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		if (isAjaxRequest(httpServletRequest)) {// 是ajax请求
			String json = "{\"type\":\"login_success\",\"message\":\"登录认证成功\"}";
			responseJson(response, json);
		} else {
			issueSuccessRedirect(request, response);
		}
		return false;
	}

	/**
	 * 主要是处理登入失败的方法
	 */
	@Override
	protected boolean onLoginFailure(AuthenticationToken token,
			AuthenticationException e, ServletRequest request,
			ServletResponse response) {
		if (isAjaxRequest((HttpServletRequest) request)) {// 是ajax请求
			String json = "{\"type\":\"login_failure\",\"message\":\""
					+ getAuthExpMessage(e) + "\"}";
			responseJson(response, json);
			return false;
		} else {
			setFailureAttribute(request, e);
			return false;
		}

	}

	/**
	 * AJAX请求响应未登录响应JSON数据
	 */
	protected void redirectToLogin(ServletRequest request,
			ServletResponse response) throws IOException {
		if (isAjaxRequest((HttpServletRequest) request)) {
			String json = "{\"type\":\"login\",\"message\":\"需要登录认证\"}";
			responseJson(response, json);
		} else {
			WebUtils.issueRedirect(request, response, getLoginUrl());
		}
	}

	/**
	 * 验证码认证
	 */
	protected void doCaptchaValidate(HttpServletRequest request,
			CaptchaUsernamePasswordToken token) {

		String captcha = (String) request.getSession().getAttribute(
				getKaptchaSessionKey());

		if (captcha != null && !captcha.equalsIgnoreCase(token.getCaptcha())) {
			throw new ShiroBadCaptchaException("验证码错误！");
		}
	}

	/**
	 * 验证码SessionKey
	 */
	protected String getKaptchaSessionKey() {
		return com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;
	}

	/**
	 * 判断是否AJAX请求
	 */
	protected boolean isAjaxRequest(HttpServletRequest request) {
		return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
	}

	/**
	 * 认证异常信息
	 */
	protected String getAuthExpMessage(AuthenticationException e) {
		String expMsg = null;
		if (e instanceof UnknownAccountException
				|| e instanceof IncorrectCredentialsException) {
			expMsg = "错误的用户账号或密码！";
		} else if (e instanceof ShiroBadCaptchaException) {
			expMsg = "验证码错误！";
		} else if (e instanceof LockedAccountException) {
			expMsg = "用户账号已禁用！";
		} else if (e instanceof ExpiredCredentialsException) {
			expMsg = "用户账号已过期！";
		} else if (e instanceof TimeLockedException) {
			expMsg = e.getMessage();
		} else {
			expMsg = "登录异常:" + e.getMessage();
		}

		return expMsg;
	}

	/**
	 * 响应JSON数据
	 */
	protected void responseJson(ServletResponse response, String json) {
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json");
		try {
			response.getWriter().write(json);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
